/*
 * @Author: hongbin
 * @Date: 2023-08-07 19:24:50
 * @LastEditors: hongbin
 * @LastEditTime: 2023-08-08 17:15:05
 * @Description:glb 贴图替代颜色
 */

import { ThreeHelper } from "@/ThreeHelper";
import { CameraInject, LoadGLTF } from "@/decorators";
import { DotMaterial } from "@/shader/DotMaterial";
import { BufferAttribute, Points } from "three";
import { gsap } from "gsap";
import { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
import { GUIControl } from "@/ThreeHelper/utils/GUIControl";

@(CameraInject<typeof Aircraft>)
export class Aircraft {
    particle?: THREE.Points<THREE.BufferGeometry, THREE.ShaderMaterial>;
    private camera!: THREE.PerspectiveCamera;
    private cameraWrapper!: THREE.Object3D;

    constructor() {
        this.loadModel();
    }

    @LoadGLTF("/models/particles/aircraft.glb")
    loadModel(gltf?: GLTF) {
        if (!gltf) return;

        const mesh = gltf.scene.getObjectByProperty(
            "type",
            "Mesh"
        ) as THREE.Mesh<THREE.BufferGeometry, THREE.MeshStandardMaterial>;
        console.log(mesh);
        mesh.geometry.scale(0.05, 0.05, 0.05);
        mesh.geometry.rotateX(Math.PI / -2);
        mesh.geometry.rotateZ(Math.PI);

        this.setSizeAttr(mesh.geometry);

        this.particle = new Points(
            mesh.geometry,
            new DotMaterial(
                {
                    near: -10,
                    far: -60,
                    fadeDistance: 7,
                    blur: 3,
                    map: mesh.material.map,
                    baseParticleSize: 1,
                },
                {
                    depthTest: false,
                }
            )
        );

        ThreeHelper.instance.add(this.particle);
        this.setAnimation();
    }

    setSizeAttr(geometry: THREE.BufferGeometry) {
        const pointCount = geometry.getAttribute("position").count;

        const size = new Float32Array(pointCount);

        for (let i = 0; i < pointCount; i++) {
            size[i] = (Math.random() + 0.1) * 2.3;
        }

        const bufferAttr = new BufferAttribute(size, 1);
        geometry.setAttribute("size", bufferAttr);
    }

    setAnimation() {
        const particle = this.particle;
        if (!particle) return;
        particle.position.set(0, -20, 35);
        new GUIControl(ThreeHelper.instance.gui!, particle, 50);
        const tl = gsap.timeline({
            scrollTrigger: {
                trigger: "#container",
                start: innerHeight * 1.5,
                end: innerHeight * 2.5,
                scrub: 1,
            },
        });

        tl.to(particle.position, { z: -50, y: -15, duration: 0.2 }, 0);
        tl.to(particle.position, { z: -75, y: 15, duration: 0.2 }, 0.2);
        tl.to(particle.rotation, { x: Math.PI / 2, duration: 0.2 }, 0.2);
        tl.to(particle.position, { z: 75, y: 10, duration: 0.4 }, 0.4);
        tl.to(particle.rotation, { x: Math.PI, duration: 0.1 }, 0.4);
        tl.to(
            this.camera,
            {
                duration: 1,
                fov: 130,
                onUpdate: () => this.camera.updateProjectionMatrix(),
            },
            0
        );
        tl.to(this.cameraWrapper.position, { z: -20, duration: 0.5 }, 0);
        tl.to(particle.material.uniforms.near, { value: 10 }, 0.3);
        tl.to(particle.material.uniforms.baseParticleSize, { value: 2 }, 0.5);
        tl.to(
            particle.material.uniforms.fadeDistance,
            { value: 4, duration: 0.3 },
            0.5
        );
        // tl.to(this.cameraWrapper.position, { z: -20 }, 0.17);
        // tl.to(
        //     this.camera,
        //     { fov: 130, onUpdate: () => this.camera.updateProjectionMatrix() },
        //     0.17
        // );
    }
}
